<!--
 * @Author: your name
 * @Date: 2021-02-09 15:24:23
 * @LastEditTime: 2021-04-30 11:13:47
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \vue3-element-admin\src\views\layoutpages\system\components\MenuEdit.vue
-->
<template>
    <el-dialog
        :title="title"
        append-to-body
        destroy-on-close
        :model-value="showDialog"
        @close="closeDialog()"
    >
        <!-- <span>{{ rowData }}</span> -->
        <!-- 表单内容 -->
        <el-form
            ref="formRef"
            :model="form"
            label-width="80px"
            :rules="rules"
            :inline="false"
        >
            <el-form-item label="类型">
                <el-radio-group v-model="type" @change="changeType">
                    <el-radio-button :disabled="typeItemDisabled(0)" :label="0"
                        >目录</el-radio-button
                    >
                    <el-radio-button :disabled="typeItemDisabled(1)" :label="1"
                        >菜单</el-radio-button
                    >
                    <el-radio-button :disabled="typeItemDisabled(2)" :label="2"
                        >按钮</el-radio-button
                    >
                </el-radio-group>
            </el-form-item>
            <el-form-item label="父级" prop="parentId">
                <el-cascader
                    style="width:100%"
                    :options="menuList"
                    v-model="parentId"
                    clearable
                    filterable
                    :props="cascaderProp"
                    @change="cascaderChange"
                    :disabled="title != '添加'"
                >
                </el-cascader>
            </el-form-item>

            <el-form-item label="排序" v-show="type != 2">
                <el-input-number
                    v-model="sort"
                    :min="0"
                    step-strictly
                    :step="1"
                >
                </el-input-number>
            </el-form-item>
            <el-form-item label="名称" prop="name" v-show="type != 2">
                <el-input v-model="name"></el-input>
            </el-form-item>
            <el-form-item label="图标" prop="icon" v-show="type != 2">
                <el-select
                    style="width:100%"
                    v-model="icon"
                    placeholder=""
                    clearable
                    filterable
                    @visible-change="handelOptionsChange"
                    popper-class="ve_option_box"
                >
                    <template v-slot:prefix>
                        <i :class="icon" style="color:#000"></i>
                    </template>
                    <el-option
                        style="display:inline-block; height:auto;padding:10px 11px 0px"
                        v-for="item in ve_icons"
                        :key="item"
                        :label="item"
                        :value="item"
                    >
                        <i
                            style="font-size:30px"
                            :title="item"
                            :class="item"
                        ></i>
                    </el-option>
                </el-select>
            </el-form-item>

            <el-form-item
                label="iframe"
                v-show="type == 1"
                @change="changeIframe()"
            >
                <el-radio-group v-model="iframe">
                    <el-radio-button :label="0">否</el-radio-button>
                    <el-radio-button :label="1">是</el-radio-button>
                </el-radio-group>
            </el-form-item>
            <el-form-item label="路径" prop="url" v-show="type == 1">
                <el-input
                    v-if="iframe == 1"
                    v-model="url"
                    placeholder="请输入"
                    clearable
                ></el-input>
                <el-select
                    v-else
                    style="width:100%"
                    v-model="url"
                    placeholder=""
                    clearable
                >
                    <el-option
                        style="height:auto"
                        v-for="item in files"
                        :key="item.url"
                        :label="item.url"
                        :value="item.url"
                    >
                        <p style="margin : 0">{{ item.url }}</p>
                        <span class="ve_select_option_slot"
                            >描述 ：{{ item.description }}</span
                        >
                    </el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="按钮" prop="menu" v-show="type == 2">
                <template v-if="menuOptions">
                    <el-radio-group v-model="menu" @change="changeMenu()">
                        <el-radio
                            v-for="(item, key) in menuOptions"
                            :key="key"
                            :label="key"
                            :disabled="menuDisabled(key)"
                            >{{ item.name }}</el-radio
                        >
                    </el-radio-group>
                </template>
                <span style="color:red" v-else>该菜单下没有按钮</span>
            </el-form-item>

            <el-form-item
                v-show="type == 2 && changeToPath"
                label="目标菜单"
                prop="toPath"
                :rules="toPathRule"
            >
                <el-cascader
                    style="width:100%"
                    :options="menuList"
                    v-model="toPath"
                    clearable
                    filterable
                    :props="{
                        expandTrigger: 'hover',
                        emitPath: false,
                        checkStrictly: true,
                        value: 'id',
                        label: 'name',
                        disabled: 'iframe'
                    }"
                >
                </el-cascader>
            </el-form-item>
        </el-form>

        <template v-slot:footer>
            <span>
                <el-button @click="closeDialog()">取消</el-button>
                <el-button type="primary" @click="onSubmit()">确定</el-button>
            </span>
        </template>
    </el-dialog>
</template>

<script>
/**
 * @description: 获取文件路径
 * @param {*}
 * @return {*}
 */
const getfiles = () => {
    const files = require.context("@/views/layoutpages", true, /\.vue$/);
    return files
        .keys()
        .map(key => {
            return {
                url: key.replace(/^(\.\/)|(\.vue)/g, ""),
                description:
                    files(key).default.data &&
                    (files(key).default.data().description || "无"),
                menus:
                    files(key).default.data &&
                    (files(key).default.data().menus || [])
            };
        })
        .filter(key => {
            return !key.url.includes("/components/");
        });
};

import { icons, treeFindPath } from "@/utils";
import { reactive, ref, toRefs, computed, nextTick, onMounted } from "vue";
// import { useStore } from "vuex";

export default {
    props: {
        showDialog: {
            type: Boolean,
            default: true
        },
        title: {
            type: String,
            default: "添加"
        },
        rowData: {
            type: Object,
            default: null
        },
        menuList: {
            type: Array,
            default: null
        }
    },
    emits: ["closeDialog"],
    setup(props, { emit }) {
        const { title, rowData, menuList } = toRefs(props);
        const closeDialog = () => {
            emit("closeDialog", false);
        };
        const ve_icons = ref([]);
        const formRef = ref(null);
        const form = reactive({
            name: "",
            type: 0,
            parentId: -1,
            menu: "",
            url: "",
            icon: "el-icon-menu",
            iframe: 1,
            sort: 1,
            toPath: ""
        });
        const {
            name,
            type,
            parentId,
            menu,
            url,
            icon,
            iframe,
            sort,
            toPath
        } = toRefs(form);
        /**
         * @description: 字段重置
         * @param {*}
         * @return {*}
         */
        const resetForm = () => {
            name.value = "";
            menu.value = "";
            url.value = "";
            icon.value = "el-icon-menu";
            iframe.value = 1;
            sort.value = 1;
            toPath.value = "";
        };

        /**
         * @description: 级联选择器props
         * @param {*} computed
         * @return {*}
         */
        const cascaderProp = computed(() => ({
            expandTrigger: "hover",
            emitPath: false,
            checkStrictly: true,
            value: "id",
            label: "name",
            disabled: type.value == 2 ? "iframe" : "type"
        }));
        /**表单验证规则
         * @description:
         * @param {*} computed
         * @return {*}
         */
        const rules = computed(() => ({
            parentId: [
                {
                    required: type.value == 2 ? true : false,
                    message: "请选择父级菜单",
                    trigger: "change"
                }
            ],
            name: [
                {
                    required: type.value != 2 ? true : false,
                    message: "请输入菜单名称",
                    trigger: "blur"
                }
            ],
            menu: [
                {
                    required: type.value == 2 ? true : false,
                    message: "请选择按钮",
                    trigger: "change"
                }
            ],
            icon: [
                {
                    required: type.value != 2 ? true : false,
                    message: "请选择图标",
                    trigger: "change"
                }
            ],

            url: [
                {
                    required: type.value == 1 ? true : false,
                    pattern: /^(https?:\/\/)?(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/i,
                    message: "url不正确",
                    trigger: "change"
                }
            ]
        }));
        /**按钮目标菜单验证规则
         * @description:
         * @param {*} computed
         * @return {*}
         */
        const toPathRule = computed(() => [
            {
                required: changeToPath.value,
                message: "请选择目标菜单",
                trigger: "change"
            },
            {
                validator: (rule, value, callback) => {
                    if (value == parentId.value) {
                        callback(new Error("不可以选择当前父级菜单"));
                    } else {
                        callback();
                    }
                },
                trigger: "change"
            }
        ]);

        /**
         * @description:初始化赋值
         * @param {*}
         * @return {*}
         */
        rowData.value &&
            ((name.value = rowData.value.name),
            (type.value = rowData.value.type),
            (parentId.value = rowData.value.parentId),
            (url.value = rowData.value.url),
            (menu.value = rowData.value.menu),
            (icon.value = rowData.value.icon),
            (iframe.value = rowData.value.iframe),
            (toPath.value = rowData.value.toPath),
            (sort.value = rowData.value.sort));
        /**
         * @description: 类型切换事件
         * @param {*}
         * @return {*}
         */
        const changeType = val => {
            formRef.value.resetFields();
            val == 2 && (icon.value = "");
        };
        /**
         * @description: 图标下拉框展开事件
         * @param {*}
         * @return {*}
         */
        const handelOptionsChange = flag => {
            if (flag === true && ve_icons.value.length < 1) {
                ve_icons.value = icons;
            }
        };
        /**
         * @description: 父级id切换事件
         * @param {*}
         * @return {*}
         */
        const cascaderChange = () => {
            if (type.value == 2) {
                name.value = "";
                menu.value = "";
                nextTick(() => {
                    formRef.value.clearValidate("menu");
                });
            }
        };
        /**
         * @description:iframe切换事件
         * @param {*}
         * @return {*}
         */
        const changeIframe = () => {
            url.value = "";
            nextTick(() => {
                if (rowData.value && iframe.value == rowData.value.iframe) {
                    url.value = rowData.value.url;
                }
                formRef.value.clearValidate("url");
            });
        };
        /**
         * @description:切换菜单按钮触发事件
         * @param {*}
         * @return {*}
         */
        const changeMenu = () => {
            name.value = menuOptions.value[menu.value]["name"];
            toPath.value = "";
            nextTick(() => {
                if (rowData.value && menu.value == rowData.value.menu) {
                    toPath.value = rowData.value.toPath;
                }
                formRef.value.clearValidate("toPath");
            });
        };
        /**
         * @description: 控制跳转菜单是否显示
         * @param {*}
         * @return {*}
         */
        const changeToPath = computed(() => {
            if (menuOptions.value && menu.value) {
                return menuOptions.value[menu.value]["toPath"];
            }
            return false;
        });
        /**
         * @description: 按钮的禁用函数
         * @param {*}
         * @return {*}
         */
        const typeItemDisabled = computed(() => label => {
            let flag = true;
            switch (title.value) {
                case "编辑":
                    if (label == type.value) {
                        flag = false;
                    }
                    break;
                case "添加子级":
                    if (label == 0 || label == 1) {
                        flag = false;
                    }
                    break;
                case "添加按钮":
                    if (label == 2) {
                        flag = false;
                    }
                    break;

                default:
                    flag = false;
                    break;
            }
            return flag;
        });

        /**
         * @description:获取menus列表
         * @param {*}
         * @return {*}
         */
        const menuOptions = computed(() => {
            // if (title.value == "添加" || title.value == "添加按钮") {
            let _item = XE.findTree(
                menuList.value,
                item => item.id == parentId.value
            );
            if (_item && getfiles().find(item => item.url == _item.item.url)) {
                return getfiles().find(item => item.url == _item.item.url)
                    .menus;
            } else {
                return false;
            }
            // }
        });
        /**
         * @description: 已添加的按钮设为禁用
         * @param {*}
         * @return {*}
         */
        const menuDisabled = computed(() => key => {
            let _item = XE.findTree(
                menuList.value,
                item => item.id == parentId.value
            );
            if (_item) {
                if (rowData.value && key == rowData.value.menu) {
                    return false;
                }
                return (
                    _item.item.children &&
                    _item.item.children.find(item => item.menu == key) &&
                    true
                );
            }
        });
        /**
         * @description: 监听title
         * @param {*}
         * @return {*}
         */
        const watchTitle = () => {
            if (title.value == "添加按钮" || title.value == "添加子级") {
                resetForm();
                parentId.value = treeFindPath(
                    menuList.value,
                    data => data.id === rowData.value.id
                ).slice(-1)[0];
                title.value == "添加按钮" &&
                    ((type.value = 2), (icon.value = ""));
            }
        };
        onMounted(() => {
            watchTitle();
        });
        /**
         * @description:提交表单
         * @param {*}
         * @return {*}
         */
        const onSubmit = () => {
            formRef.value.validate(async valid => {
                if (valid) {
                    let res;
                    if (title.value.includes("添加")) {
                        res = await VE_API.system.menuAdd(form);
                    } else {
                        res = await VE_API.system.menuEdit({
                            id: rowData.value.id,
                            ...form
                        });
                    }
                    const { code } = res;
                    if (code == "00") {
                        closeDialog();
                    }
                } else {
                    console.log("error submit!!");
                    return false;
                }
            });
        };
        return {
            icons,
            files: getfiles(),
            closeDialog,
            onSubmit,
            changeType,
            changeIframe,
            typeItemDisabled,
            // menuList,
            formRef,
            rules,
            form,
            ...{ name, type, parentId, menu, url, icon, iframe, sort, toPath },
            cascaderProp,
            menuOptions,
            menuDisabled,
            cascaderChange,
            changeMenu,
            changeToPath,
            toPathRule,
            handelOptionsChange,
            ve_icons
        };
    }
};
</script>

<style lang="scss" scoped></style>
